package mc0101.mccache.util;

import mc0101.mccache.api.ZcRedisHandleApi;
import mc0101.mccache.param.ZcCacheParam;
import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 缓存有效性判断工具
 */
@Component
@Slf4j
public class CacheInvalidJudgeUtils {


    @Autowired
    private ZcRedisHandleApi zcRedisHandleApi;

    @Autowired
    private ZcCacheParam zcCacheParam;

    private volatile long localCacheVersion = 0L;

    private volatile long oldErrorQueryTimestamp = 0L;

    private volatile long oldUsuallyQueryTimestamp = 0L;

    @Value("${cache.outTime.remoteErrorRefresh:1800000}")
    private long remoteErrorRefreshOutTime;

    @Value("${cache.outTime.localUsuallyRefresh:3000}")
    private long localUsuallyRefreshOutTime;

    public boolean isTimeOutAndInvalid(){
        if (isTimeOut() && isInvalid()){
            // 只有当本地缓存超时同时缓存（远程或本地）失效的时候，才会去刷新缓存
            return true;
        }
        return false;
    }

    public boolean isTimeOut(){
        return isUsuallyTimeOut();
    }

    public boolean isInvalid(){
        String paramVersionKey = zcCacheParam.getParamVersionKey();

        long begin = System.currentTimeMillis();
        String paramVersionString = zcRedisHandleApi.get(paramVersionKey);
        log.debug("查询redis版本号耗时："+(System.currentTimeMillis()-begin));

        refreshUsuallyTimeOut();

        long remoteCacheVersion = Long.parseLong(paramVersionString != null ? paramVersionString : "0");
        // 当本地缓存版本和远程版本不相等的时候，可能远程版本失效了，或者本地版本失效了，这时候都属于失效
        return !isLocalVersionEquals(remoteCacheVersion);
    }

    public boolean isErrorTimeOut(){
        if (System.currentTimeMillis() - oldErrorQueryTimestamp > remoteErrorRefreshOutTime){
            return true;
        }
        return false;
    }

    public boolean isLocalVersionEquals(long remoteCacheVersion){
        return remoteCacheVersion == localCacheVersion;
    }

    public boolean isLocalVersionEqualsOrNew(long remoteCacheVersion){
        return remoteCacheVersion <= localCacheVersion;
    }

    public boolean isLocalVersionOld(long remoteCacheVersion){
        return remoteCacheVersion > localCacheVersion;
    }

    public boolean isUsuallyTimeOut() {
        if (System.currentTimeMillis() - oldUsuallyQueryTimestamp > localUsuallyRefreshOutTime){
            return true;
        }
        return false;
    }

    public void refreshUsuallyTimeOut(){
        oldUsuallyQueryTimestamp = System.currentTimeMillis();
    }


    public long getLocalCacheVersion(){
        return this.localCacheVersion;
    }


    public void refreshVersionAndTimestamp(Long paramVersion) {
        localCacheVersion = paramVersion;
        oldErrorQueryTimestamp = System.currentTimeMillis();
    }
}
